package com.lily.aidouzixun.datacenter;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 *  
 * @author robotion_jing 2012.01.02
 * @param <T>
 */
public class ListPageAble<T> implements Iterable<T>, ReleaseAble {
	String ErrorType;
	String Message;
	List<T> Objects;
	private String TimeStamp;
	private int DefaultLimitListLen = 30 * 50;
	int PageSize = 30;
	private int RemoteTotalPageNums = 1;
	private int RemotePageSize = 30;
	private int CurRemotePage = 1;
	private int CurPage = 1;
	private int lastVisiblePos = 0;
	private boolean HasNoMoreDatas = false;
	
	public String getErrorType() {
		return ErrorType;
	}

	public void setErrorType(String errorType) {
		ErrorType = errorType;
	}
	
	public String getMessage() {
		return Message;
	}

	public void setMessage(String message) {
		Message = message;
	}

	public void setLimit(int limit) {
		DefaultLimitListLen = limit;
	}

	public void setPageSize(int len) {
		if (len >= 1)
			PageSize = len;
	}

	public int getPageSize() {
		return PageSize;
	}

	public void setNoMoreDatas(boolean hasNoMoreDatas) {
		HasNoMoreDatas = hasNoMoreDatas;
	}

	public boolean isNoMoreDatas() {
		return HasNoMoreDatas;
	}

	public void setRemoteTotalPageNum(int PageNums) {
		RemoteTotalPageNums = PageNums;
	}

	public int getRemoteTotalPageNum() {
		return RemoteTotalPageNums;
	}

	void setRemotePageSize(int PageSize) {
		RemotePageSize = PageSize;
	}

	public int getRemotePageSize() {
		return RemotePageSize;
	}

	public void setCurRemotePage(int PageNum) {
		CurRemotePage = PageNum;
	}

	public int getCurRemotePage() {
		return CurRemotePage;
	}

	public int getTotalPageNum() {
		return 1 + (RemoteTotalPageNums * RemotePageSize - 1) / PageSize;
	}

	/**
	 * 
	 * @return if no datas return 0;
	 */
	public int getCurPageNums() {
		return size() / PageSize;
	}

	/**
	 * 
	 * @return PageNo. start from 1
	 */
	public int getCurPage() {
		return CurPage;
	}

	public boolean isNeedLoadRemoteStaticPage() {
		if (CurPage < 1 + (size() - 1) / PageSize)
			return false;
		else {
			if (CurRemotePage < RemoteTotalPageNums)
				return true;
			else
				return false;
		}
	}

	public boolean isNeedLoadRemoteDymaicPage() {
		if (CurPage < 1 + (size() - 1) / PageSize)
			return false;
		else {
			return true;
		}
	}

	public int getNextRemotePageNum() {
		return CurRemotePage + 1;
	}

	/**
	 * 
	 * @return timestamp or empty
	 */
	public String getTimeStamp() {
		if (TimeStamp == null)
			return "";
		return TimeStamp;
	}

	public void setTimeStamp(String timeStamp) {
		TimeStamp = timeStamp;
	}

	public void setObjects(List<T> objects) {
		Objects = objects;
	}

	public List<T> getDatas() {
		return Objects;
	}
 
	
	public int getSize() {
		if (Objects == null)
			return 0;
		return Objects.size();
	}

	/**
	 * 
	 * @param limitListLen zero as default limitLen
	 */
	public void addHead(List<T> objects, int limitListLen) {
		if (objects == null)
			return;
		if (Objects == null)
			Objects = objects;
		else {
			Objects.addAll(0, objects);
			ReleaseRemains(limitListLen);
		}
	}

	/**
	 * be sure the limitListLen has been set, or using Default Length
	 * 
	 * @param objects
	 */
	public void addHead(List<T> objects) {
		addHead(objects, DefaultLimitListLen);
	}

	public void addItemahead(T info) {
		if (Objects == null)
			Objects = new ArrayList<T>();
		if (Objects != null && info != null)
			Objects.add(0, info);
	}

	public void addTail(T info) {
		if (Objects == null)
			Objects = new ArrayList<T>();
		if (Objects != null && info != null)
			Objects.add(info);
	}

	/**
	 * 
	 * @param limitListLen  zero as default limitLen
	 */
	public void addTail(List<T> objects, int limitListLen) {
		if (objects == null)
			return;
		if (Objects == null) {
			Objects = objects;
			setLastVisiblePos(0);
			return;
		} else {
			int oldSize = getSize();
			Objects.addAll(objects);
			int removedSize = ReleaseHeadRemains(limitListLen);			
			setLastVisiblePos(oldSize - removedSize - 1);
 		}
	}

	/**
	 * start position =0; items = PageNum*PageSize
	 * 
	 * @param PageNum  start from 1
	 * @param PageSize
	 * @return null or the result
	 */
	public List<T> getPagesOfDatas(int PageNum, int PageSize) {
		int size = getSize();
		if (size == 0)
			return null;
		int end = PageNum * PageSize;
		if (size < end)
			end = size;
		return Objects.subList(0, end);
	}

	/**
	 * start position =0; items = PageNum*PageSize
	 * 
	 * @param PageNum  start from 1
	 * @return null or the result
	 */
	public List<T> getPagesOfDatas(int PageNum) {
		CurPage = PageNum;
		return getPagesOfDatas(PageNum, PageSize);
	}

	/**
	 * start position = (thePage-1) * PageSize, end position = thePage * PageSize
	 * 
	 * @param thePage  start from 1
	 * @param pageSize
	 * @return null or the result
	 */
	public List<T> getThePage(int thePage, int pageSize) {
		CurPage = thePage;
		if (pageSize <= 0)
			pageSize = PageSize;
		int size = getSize();
		if (size == 0)
			return null;
		int start = (thePage - 1) * pageSize;
		if (start < 0)
			start = 0;
		int end = thePage * pageSize;
		if (size < end)
			end = size; 
		return Objects.subList(start, end);
	}

	public int getLastVisiblePos() {
		return lastVisiblePos;
	}
	
	public void setLastVisiblePos(int pos) {
		if(pos >= 0)
			lastVisiblePos = pos;
	}

	/**
	 * start position = thePage * PageSize, end position = (thePage+1) * PageSize
	 * 
	 * @param thePage  start from 1
	ImageAble.java
	ImageInfo.java	 * @return null or the result
	 */
	public List<T> getThePage(int thePage) {
		return getThePage(thePage, PageSize);
	}

	/**
	 * 
	 * @param limitListLen  zero as default limitLen
	 * @return removed data size
	 */
	private int ReleaseRemains(int limitListLen) {
		if (Objects == null)
			return 0;
		if (limitListLen <= 0)
			limitListLen = DefaultLimitListLen;
		List<? extends Object> tempList = Objects;

		int len = getSize() - limitListLen;
		for (int i = 0; i < len; i++) {
			int index = getSize() - 1;
			Object item = tempList.remove(index);
			/*todo if(item instanceof ImageAble) {
				((ImageAble) item).Release();
			}*/
		}
		return len > 0 ? len : 0;
	}

	/**
	 * 
	 * @param limitListLen zero as default limitLen
	 * @return removed data size
	 */
	public int ReleaseHeadRemains(int limitListLen) {
		if (Objects == null)
			return 0;
		if (limitListLen <= 0)
			limitListLen = DefaultLimitListLen;
		List<? extends Object> tempList = Objects;

		int len = getSize() - limitListLen;
		for (int i = 0; i < len; i++) {
			Object item = tempList.remove(0);
			// todo ((ImageAble) item).Release();
		}
		return len > 0 ? len : 0;
	}

	public T getItem(int index) {
		if (index < 0 || index >= size())
			return null;
		return Objects.get(index);
	}

	/**
	 * 
	 * @param index
	 * @return the removed obj or null
	 */
	
	public T remove(int index) {
		if (index < 0 || index >= size())
			return null;
		return Objects.remove(index);
	}

	/**
	 * the exactly position = posInPage + PageNum*PageSize<br>
	 * position start from zero <br>
	 * 
	 * @param posInPage
	 *            start from zero
	 * @param PageNum
	 *            start from zero
	 * @param PageSize
	 * @return
	 */
	public T getItem(int posInPage, int PageNum, int PageSize) {
		return getItem(posInPage + PageNum * PageSize);
	}

	public void clear() {
		if (Objects != null)
			Objects.clear();
	}

	public int size() {
		if (Objects != null)
			return Objects.size();
		else
			return 0;
	}
	
	/**
	 * the array or null
	 */
	@SuppressWarnings("unchecked")	
	public T[] toArray() {
		if(Objects != null)
			return (T[]) Objects.toArray();
		return null;
	}

	 /**
	  * the Iterator or null
	  */
	 public Iterator<T> iterator() {
		 if (Objects != null)
			 return Objects.iterator();
		 return null;
	}
 	
    @Override
    public String toString() {
    	// TODO Auto-generated method stub
    	return super.toString() + ", datas=" + Objects;
    }

	@Override
	public void Release() {
		if (Objects != null) {
			for(T info: Objects) {
				if(info instanceof ReleaseAble) {
					((ReleaseAble) info).Release();
				}
			}
		}		
		clear();		
	} 
	 
}
